import net.nutss.*;
import net.nutss.stunt.*;
import java.net.*;
/*
by casper not supported
import java.io.*;
*/
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.Semaphore;


class EchoServerUDP {

    static Semaphore semaphore = new Semaphore(0);

    static LinkedList<DatagramChannel> sockets = new LinkedList<DatagramChannel>();
    static LinkedList<URI> uris = new LinkedList<URI>();
    static URI i;

    static class Handler extends STUNTEventAdapter {

        public void acceptUDPHandler(DatagramChannel sock, URI remoteAddress) {
            synchronized(semaphore) {
                sockets.addLast(sock);
                uris.addLast(remoteAddress);
                semaphore.release();
            }
        }

        public void errorHandler(Exception e) {
            System.err.println("An error occurred. If this is unexpected, please run with '-d'\n" +
                               "as the first argument and email the log created in EchoServerLog.txt\n" +
                               "to Saikat Guha <saikat@cs.cornell.edu>. Thanks\n");
            e.printStackTrace();
            System.exit(1);
        }
    }

    static class Responder extends Thread {

        ByteBuffer o = ByteBuffer.allocate(1300);
        DatagramChannel s;

        void close() {
            try { if (s != null) s.close(); } catch (Exception e) { }
        }

        Responder(DatagramChannel s, URI u) {
            try {
                String m = "Greetings "+u+", this is the EchoServer at "+i+". Now you say something.";
                o.put(m.getBytes());
                o.flip();
                System.out.println("Accepted "+u);
                this.s = s;
            } catch (Exception e) { e.printStackTrace(); close(); }
        }

        public void run() {
            try {
                Thread.sleep(1000);
                s.write(o);
                s.socket().setSoTimeout(300);
                while(true) {
                    o.clear();
                    s.receive(o);
                    o.flip();
                    s.write(o);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally { close(); }
        }
    }

    public static void main(String[] arg) throws Exception {
        try {
            i = new URI(arg[0].equals("-d") ? arg[1] : arg[0]);
        } catch (Exception e) {
            System.out.printf("Usage:\n\tjava EchoServer [-d] you@your.domain.com\n");
            System.exit(1);
        }
        try {
            //if (arg[0].equals("-d")) Control.logToFile("EchoServerLog.txt");
            STUNTEndpoint sock = new STUNTEndpoint(i);
            sock.listen(new Handler());
            while (true) {
                semaphore.acquire();
                synchronized(semaphore) {
                    new Responder(sockets.removeFirst(), uris.removeFirst()).start();
                }
            }
        } catch (Exception e) {
            System.err.println("An error occurred. If this is unexpected, please run with '-d'\n" +
                    "as the first argument and email the log created in EchoServerLog.txt\n" +
                    "to Saikat Guha <saikat@cs.cornell.edu>. Thanks\n");
            e.printStackTrace();
            System.exit(1);
        }
    }
}
